GY-30光照传感器的具体资料可以去淘宝搜索然后问卖家要,网上也有,所以这里我就不多嘴了。
VCC连接3到5伏电压,根据文件开头的描述在STM32CubeMX中配置好外设。
STM32Cube开发方式就是4个字“简单直接”,直接上代码。
gy30.h
#ifndef __GY30_H__
#define __GY30_H__
#include "main.h"
//main函数里需要使用的就这一个输入亮度变量的地址,返回读取状态
uint8_t Z_GY30_GetData(uint16_t *nowLum);
void Z_I2C_Start(void);
void Z_I2C_End(void);
void Z_I2C_SendByte(uint8_t byte);
uint8_t Z_I2C_ReveiceByte();
void Z_I2C_SendACK(uint8_t ack);
uint8_t Z_I2C_ReveiceACK();
#endif
gy30.c
/********************************************************************************
* 作 者:洛宇航(SiriusIoT)
* 名 称:
* 备 注:
* CubeMX配置方法:
* 1.软件I2C
* 选择两个GPIO引脚作为软件I2C引脚。
* 建议命名为softI2C1_SCL,softI2C1_SDA
* 默认输出高电平、开漏输出、上拉、25MHz
* 2.毫秒级延时
* 选择定时器,配置为每毫秒技术一次,无需开中断(默认为TIM6)
*******************************************************************************/
#include "gy30.h"
#include "tim.h"
//外设配置宏定义start
#define DHT_HTIM htim6//微秒级延时,使用了定时器6
//定义i2c总线连接的GPIO端口, 用户只需要修改下面5段行代码即可任意改变SCL和SDA的引脚
#define GPIO_PORT_GY30 GPIOE //GY30 GPIO端口
//软件I2C外设配置
#define GY30_SCL_PORT softI2C1_SCL_GPIO_Port
#define GY30_SCL_PIN softI2C1_SCL_Pin
#define GY30_SDA_PORT softI2C1_SDA_GPIO_Port
#define GY30_SDA_PIN softI2C1_SDA_Pin
//定义读写SCL和SDA的宏
//SCL = 1
#define GY30_SCL_1 HAL_GPIO_WritePin(GY30_SCL_PORT, GY30_SCL_PIN, GPIO_PIN_SET)
//SCL = 0
#define GY30_SCL_0 HAL_GPIO_WritePin(GY30_SCL_PORT, GY30_SCL_PIN, GPIO_PIN_RESET)
//读SCL口线状态
#define GY30_SCL_READ HAL_GPIO_ReadPin(GY30_SCL_PORT, GY30_SCL_PIN)
//SDA = 1
#define GY30_SDA_1 HAL_GPIO_WritePin(GY30_SDA_PORT, GY30_SDA_PIN, GPIO_PIN_SET)
//SDA = 0
#define GY30_SDA_0 HAL_GPIO_WritePin(GY30_SDA_PORT, GY30_SDA_PIN, GPIO_PIN_RESET)
//读SDA口线状态
#define GY30_SDA_READ HAL_GPIO_ReadPin(GY30_SDA_PORT, GY30_SDA_PIN)
//外设配置宏定义end
#define SCL_Pin GPIO_Pin_0
#define SDA_Pin GPIO_Pin_1
//利用定时器微秒级延时
void GY30_Delay_us(uint16_t us)
{
uint16_t differ = 0xffff-us-5;
__HAL_TIM_SET_COUNTER(&DHT_HTIM,differ);
HAL_TIM_Base_Start(&DHT_HTIM);
while(differ < 0xffff-5)
{
differ = __HAL_TIM_GET_COUNTER(&DHT_HTIM);
}
HAL_TIM_Base_Stop(&DHT_HTIM);
}
void Z_I2C_SetSCL(uint8_t signal){
if(signal==1) GY30_SCL_1;
else GY30_SCL_0;
GY30_Delay_us(5); //防止电平翻转过快,因此加上延时
}
void Z_I2C_SetSDA(uint8_t signal){
if(signal==1) GY30_SDA_1;
else GY30_SDA_0;
GY30_Delay_us(5);
}
void Z_I2C_Start(void){
Z_I2C_SetSDA(1);
Z_I2C_SetSCL(1);
Z_I2C_SetSDA(0);
Z_I2C_SetSCL(0);
}
void Z_I2C_End(){
Z_I2C_SetSDA(0);
Z_I2C_SetSCL(1);
Z_I2C_SetSDA(1);
}
void Z_I2C_SendByte(uint8_t byte){
Z_I2C_SetSCL(0);
for(int i=0;i<8;++i){
if((byte&0x80)==0) Z_I2C_SetSDA(0);
else Z_I2C_SetSDA(1);
byte<<=1;
Z_I2C_SetSCL(1);
Z_I2C_SetSCL(0);
}
}
uint8_t Z_I2C_ReveiceByte(){
uint8_t data=0x00;
Z_I2C_SetSDA(1);
for(int i=0;i<8;++i){
Z_I2C_SetSCL(1);
if(GY30_SDA_READ==1) data|=(0x80>>i);
Z_I2C_SetSCL(0);
}
return data;
}
void Z_I2C_SendACK(uint8_t ack){
if(ack==0) Z_I2C_SetSDA(0);
else Z_I2C_SetSDA(1);
Z_I2C_SetSCL(1);
Z_I2C_SetSCL(0);
}
uint8_t Z_I2C_ReveiceACK(){
Z_I2C_SetSDA(1);
Z_I2C_SetSCL(1);
uint8_t ack=GY30_SDA_READ;
Z_I2C_SetSCL(0);
return ack;
}
uint8_t Z_GY30_GetData(uint16_t* nowLum)
{
Z_I2C_Start();
Z_I2C_SendByte(0x46);
if(Z_I2C_ReveiceACK()!=0)
return 0;
Z_I2C_SendByte(0x01);
if(Z_I2C_ReveiceACK()!=0)
return 0;
Z_I2C_End();
Z_I2C_Start();
Z_I2C_SendByte(0x46);
if(Z_I2C_ReveiceACK()!=0)
return 0;
Z_I2C_SendByte(0x10);
if(Z_I2C_ReveiceACK()!=0)
return 0;
Z_I2C_End();
HAL_Delay(200);
uint16_t Light=0;
Z_I2C_Start();
Z_I2C_SendByte(0x47);
if(Z_I2C_ReveiceACK()!=0)
return 0;
Light|=Z_I2C_ReveiceByte();
Light<<=8;
Z_I2C_SendACK(0);
Light|=Z_I2C_ReveiceByte();
Z_I2C_SendACK(1);
Z_I2C_End();
*nowLum = Light;
return 1;
}